﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using PdfSharp.Pdf;
using PdfSharp.Drawing;
using VAdvantage.Utility;
using VAdvantage.Classes;
using VAdvantage.Logging;
using VAdvantage.Model;
using System.Data;
using VAdvantage.DataBase;
using VAdvantage.Login;
using System.Data.SqlClient;
using VAdvantage.Process;
using System.Threading;
using System.Text;
using VAdvantage.ProcessEngine;

namespace VAdvantage.Print
{
    public class ReportEngine
    {
        /**	View					*/
        private View m_view = null;

        public ReportEngine(Ctx ctx, MPrintFormat pf, Query query, PrintInfo info)
        {
            if (pf == null)
                throw new ArgumentException("ReportEngine - no PrintFormat");
            log.Info(pf + " -- " + query);
            m_ctx = ctx;
            m_printerName = m_ctx.GetPrinterName();
            //
            m_printFormat = pf;
            m_info = info;
            SetQuery(query);		//	loads Data
        }	//	ReportEngine


        /// <summary>
        /// Get Document Print Engine for Document Type.
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="type"></param>
        /// <param name="Record_ID"></param>
        /// <returns>Report Engine or null</returns>
        public static ReportEngine Get(Ctx ctx, int type, int Record_ID)
        {
            if (Record_ID < 1)
            {
                log.Log(Level.WARNING, "No PrintFormat for Record_ID=" + Record_ID
                        + ", Type=" + type);
                return null;
            }
            //	Order - Print Shipment or Invoice
            if (type == ORDER)
            {
                int[] what = GetDocumentWhat(Record_ID);
                if (what != null)
                {
                    type = what[0];
                    Record_ID = what[1];
                }
            }	//	Order
            //
            //	String JobName = DOC_BASETABLES[type] + "_Print";
            int AD_PrintFormat_ID = 0;
            int C_BPartner_ID = 0;
            String DocumentNo = null;
            int copies = 1;

            //	Language
            MClient client = MClient.Get(ctx);
            Language language = client.GetLanguage();
            //	Get Document Info
            String sql = null;
            if (type == CHECK)
                sql = "SELECT bad.Check_PrintFormat_ID,"								//	1
                    + "	c.IsMultiLingualDocument,bp.AD_Language,bp.C_BPartner_ID,d.DocumentNo "		//	2..5
                    + "FROM C_PaySelectionCheck d"
                    + " INNER JOIN C_PaySelection ps ON (d.C_PaySelection_ID=ps.C_PaySelection_ID)"
                    + " INNER JOIN C_BankAccountDoc bad ON (ps.C_BankAccount_ID=bad.C_BankAccount_ID AND d.PaymentRule=bad.PaymentRule)"
                    + " INNER JOIN AD_Client c ON (d.AD_Client_ID=c.AD_Client_ID)"
                    + " INNER JOIN C_BPartner bp ON (d.C_BPartner_ID=bp.C_BPartner_ID) "
                    + "WHERE d.C_PaySelectionCheck_ID=@recordid";		//	info from BankAccount
            else if (type == DUNNING)
                sql = "SELECT dl.Dunning_PrintFormat_ID,"
                    + " c.IsMultiLingualDocument,bp.AD_Language,bp.C_BPartner_ID,dr.DunningDate "
                    + "FROM C_DunningRunEntry d"
                    + " INNER JOIN AD_Client c ON (d.AD_Client_ID=c.AD_Client_ID)"
                    + " INNER JOIN C_BPartner bp ON (d.C_BPartner_ID=bp.C_BPartner_ID)"
                    + " INNER JOIN C_DunningRun dr ON (d.C_DunningRun_ID=dr.C_DunningRun_ID)"
                    + " INNER JOIN C_DunningLevel dl ON (dl.C_DunningLevel_ID=dr.C_DunningLevel_ID) "
                    + "WHERE d.C_DunningRunEntry_ID=@recordid";			//	info from Dunning
            else if (type == REMITTANCE)
                sql = "SELECT pf.Remittance_PrintFormat_ID,"
                    + " c.IsMultiLingualDocument,bp.AD_Language,bp.C_BPartner_ID,d.DocumentNo "
                    + "FROM C_PaySelectionCheck d"
                    + " INNER JOIN AD_Client c ON (d.AD_Client_ID=c.AD_Client_ID)"
                    + " INNER JOIN AD_PrintForm pf ON (c.AD_Client_ID=pf.AD_Client_ID)"
                    + " INNER JOIN C_BPartner bp ON (d.C_BPartner_ID=bp.C_BPartner_ID) "
                    + "WHERE d.C_PaySelectionCheck_ID=@recordid"		//	info from PrintForm
                    + " AND pf.AD_Org_ID IN (0,d.AD_Org_ID) ORDER BY pf.AD_Org_ID DESC";
            else if (type == PROJECT)
                sql = "SELECT pf.Project_PrintFormat_ID,"
                    + " c.IsMultiLingualDocument,bp.AD_Language,bp.C_BPartner_ID,d.Value "
                    + "FROM C_Project d"
                    + " INNER JOIN AD_Client c ON (d.AD_Client_ID=c.AD_Client_ID)"
                    + " INNER JOIN AD_PrintForm pf ON (c.AD_Client_ID=pf.AD_Client_ID)"
                    + " LEFT OUTER JOIN C_BPartner bp ON (d.C_BPartner_ID=bp.C_BPartner_ID) "
                    + "WHERE d.C_Project_ID=@recordid"					//	info from PrintForm
                    + " AND pf.AD_Org_ID IN (0,d.AD_Org_ID) ORDER BY pf.AD_Org_ID DESC";
            else if (type == RFQ)
                sql = "SELECT COALESCE(t.AD_PrintFormat_ID, pf.AD_PrintFormat_ID),"
                    + " c.IsMultiLingualDocument,bp.AD_Language,bp.C_BPartner_ID,rr.Name "
                    + "FROM C_RfQResponse rr"
                    + " INNER JOIN C_RfQ r ON (rr.C_RfQ_ID=r.C_RfQ_ID)"
                    + " INNER JOIN C_RfQ_Topic t ON (r.C_RfQ_Topic_ID=t.C_RfQ_Topic_ID)"
                    + " INNER JOIN AD_Client c ON (rr.AD_Client_ID=c.AD_Client_ID)"
                    + " INNER JOIN C_BPartner bp ON (rr.C_BPartner_ID=bp.C_BPartner_ID),"
                    + " AD_PrintFormat pf "
                    + "WHERE pf.AD_Client_ID IN (0,rr.AD_Client_ID)"
                    + " AND pf.AD_Table_ID=725 AND pf.IsTableBased='N'"	//	from RfQ PrintFormat
                    + " AND rr.C_RfQResponse_ID=@recordid "				//	Info from RfQTopic
                    + "ORDER BY t.AD_PrintFormat_ID, pf.AD_Client_ID DESC, pf.AD_Org_ID DESC";
            else if (type == MOVEMENT)
                sql = "SELECT pf.Movement_PrintFormat_ID,"
                    + " c.IsMultiLingualDocument, COALESCE(dt.DocumentCopies,0) "
                    + "FROM M_Movement d"
                    + " INNER JOIN AD_Client c ON (d.AD_Client_ID=c.AD_Client_ID)"
                    + " INNER JOIN AD_PrintForm pf ON (d.AD_Client_ID=pf.AD_Client_ID OR pf.AD_Client_ID=0)"
                    + " LEFT OUTER JOIN C_DocType dt ON (d.C_DocType_ID=dt.C_DocType_ID) "
                    + "WHERE d.M_Movement_ID=@recordid"                 //  info from PrintForm
                    + " AND pf.AD_Org_ID IN (0,d.AD_Org_ID) AND pf.Movement_PrintFormat_ID IS NOT NULL "
                    + "ORDER BY pf.AD_Client_ID DESC, pf.AD_Org_ID DESC";
            else if (type == INVENTORY)
                sql = "SELECT pf.Inventory_PrintFormat_ID,"
                    + " c.IsMultiLingualDocument, COALESCE(dt.DocumentCopies,0) "
                    + "FROM M_Inventory d"
                    + " INNER JOIN AD_Client c ON (d.AD_Client_ID=c.AD_Client_ID)"
                    + " INNER JOIN AD_PrintForm pf ON (d.AD_Client_ID=pf.AD_Client_ID OR pf.AD_Client_ID=0)"
                    + " LEFT OUTER JOIN C_DocType dt ON (d.C_DocType_ID=dt.C_DocType_ID) "
                    + "WHERE d.M_Inventory_ID=@recordid"                 //  info from PrintForm
                    + " AND pf.AD_Org_ID IN (0,d.AD_Org_ID) AND pf.Inventory_PrintFormat_ID IS NOT NULL "
                    + "ORDER BY pf.AD_Client_ID DESC,  pf.AD_Org_ID DESC";
            else	//	Get PrintFormat from Org or 0 of document client
            {
                sql = "SELECT pf.Order_PrintFormat_ID,pf.Shipment_PrintFormat_ID,"		//	1..2
                    //	Prio: 1. BPartner 2. DocType, 3. PrintFormat (Org)	//	see InvoicePrint
                    + " COALESCE (bp.Invoice_PrintFormat_ID,dt.AD_PrintFormat_ID,pf.Invoice_PrintFormat_ID)," // 3
                    + " pf.Project_PrintFormat_ID, pf.Remittance_PrintFormat_ID,"		//	4..5
                    + " c.IsMultiLingualDocument, bp.AD_Language,"						//	6..7
                    + " COALESCE(dt.DocumentCopies,0)+COALESCE(bp.DocumentCopies,1), " 	// 	8
                    + " dt.AD_PrintFormat_ID,bp.C_BPartner_ID,d.DocumentNo "			//	9..11
                    + "FROM " + DOC_BASETABLES[type] + " d"
                    + " INNER JOIN AD_Client c ON (d.AD_Client_ID=c.AD_Client_ID)"
                    + " INNER JOIN AD_PrintForm pf ON (c.AD_Client_ID=pf.AD_Client_ID)"
                    + " INNER JOIN C_BPartner bp ON (d.C_BPartner_ID=bp.C_BPartner_ID)"
                    + " LEFT OUTER JOIN C_DocType dt ON (d.C_DocType_ID=dt.C_DocType_ID) "
                    + "WHERE d." + DOC_IDS[type] + "=@recordid"			//	info from PrintForm
                    + " AND pf.AD_Org_ID IN (0,d.AD_Org_ID) "
                    + "ORDER BY pf.AD_Org_ID DESC";
            }
            //
            try
            {
                SqlParameter[] param = new SqlParameter[1];
                param[0] = new SqlParameter("@recordid", Record_ID);
                IDataReader dr = DB.ExecuteReader(sql, param);
                if (dr.Read())
                {
                    if (type == CHECK || type == DUNNING || type == REMITTANCE
                        || type == PROJECT || type == RFQ)
                    {
                        AD_PrintFormat_ID = Util.GetValueOfInt(dr[0]);// rs.getInt(1);
                        copies = 1;
                        //	Set Language when enabled
                        String AD_Language = Util.GetValueOfString(dr[2]);// rs.getString(3);
                        if (AD_Language != null)// && "Y".equals(rs.getString(2)))	//	IsMultiLingualDocument
                            language = Language.GetLanguage(AD_Language);
                        C_BPartner_ID = Util.GetValueOfInt(dr[3]);// rs.getInt(4);
                        if (type == DUNNING)
                        {
                            DateTime? ts = Util.GetValueOfDateTime(dr[4]);// rs.getTimestamp(5);
                            DocumentNo = ts.ToString();
                        }
                        else
                            DocumentNo = Util.GetValueOfString(dr[4]);// rs.getString(5);
                    }
                    else if (type == MOVEMENT || type == INVENTORY)
                    {
                        AD_PrintFormat_ID = Util.GetValueOfInt(dr[0]);// rs.getInt(1);
                        copies = Util.GetValueOfInt(dr[2]);// rs.getInt(3);
                        if (copies == 0)
                            copies = 1;
                    }
                    else
                    {
                        //	Set PrintFormat
                        AD_PrintFormat_ID = Util.GetValueOfInt(dr[type]);// rs.getInt(type + 1);
                        if (Util.GetValueOfInt(dr[8].ToString()) != 0)		//	C_DocType.AD_PrintFormat_ID
                            AD_PrintFormat_ID = Util.GetValueOfInt(dr[8].ToString());// rs.getInt(9);
                        copies = Util.GetValueOfInt(dr[7].ToString());// rs.getInt(8);
                        //	Set Language when enabled
                        String AD_Language = Util.GetValueOfString(dr[6].ToString());// rs.getString(7);
                        if (AD_Language != null) // && "Y".equals(rs.getString(6)))	//	IsMultiLingualDocument
                            language = Language.GetLanguage(AD_Language);
                        C_BPartner_ID = Util.GetValueOfInt(dr[9]);// rs.getInt(10);
                        DocumentNo = Util.GetValueOfString(dr[10]);// rs.getString(11);
                    }
                }
                dr.Close();
            }
            catch (Exception e)
            {
                log.Log(Level.SEVERE, "Record_ID=" + Record_ID + ", SQL=" + sql, e);
            }
            if (AD_PrintFormat_ID == 0)
            {
                log.Log(Level.SEVERE, "No PrintFormat found for Type=" + type + ", Record_ID=" + Record_ID);
                return null;
            }

            //	Get Format & Data
            MPrintFormat format = MPrintFormat.Get(ctx, AD_PrintFormat_ID, false);
            format.SetLanguage(language);		//	BP Language if Multi-Lingual
            //	if (!Env.isBaseLanguage(language, DOC_TABLES[type]))
            format.SetTranslationLanguage(language);
            //	query
            Query query = new Query(DOC_TABLES[type]);
            query.AddRestriction(DOC_IDS[type], Query.EQUAL, Util.GetValueOfInt(Record_ID));
            //	log.config( "ReportCtrl.startDocumentPrint - " + format, query + " - " + language.getAD_Language());
            //
            if (DocumentNo == null || DocumentNo.Length == 0)
                DocumentNo = "DocPrint";
            PrintInfo info = new PrintInfo(
                DocumentNo,
                DOC_TABLE_ID[type],
                Record_ID,
                C_BPartner_ID);
            info.SetCopies(copies);
            info.SetDocumentCopy(false);		//	true prints "Copy" on second

            //	Engine
            ReportEngine re = new ReportEngine(ctx, format, query, info);
            return re;
        }


        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="ctx">current context</param>
        /// <param name="pi">process info</param>
        /// <returns>same class object</returns>
        static public ReportEngine Get(Ctx ctx, ProcessInfo pi)
        {
            int AD_Client_ID = (int)pi.GetAD_Client_ID();
            //
            int AD_Table_ID = 0;
            int AD_ReportView_ID = 0;
            String TableName = null;
            String whereClause = "";
            String orderbyClause = "";
            int AD_PrintFormat_ID = 0;
            bool IsForm = false;
            int Client_ID = -1;

            //	Get AD_Table_ID and TableName
            String sql = "SELECT rv.AD_ReportView_ID,rv.WhereClause, "
                + " t.AD_Table_ID,t.TableName, pf.AD_PrintFormat_ID, pf.IsForm, pf.AD_Client_ID, rv.OrderByClause "
                + "FROM AD_PInstance pi"
                + " INNER JOIN AD_Process p ON (pi.AD_Process_ID=p.AD_Process_ID)"
                + " INNER JOIN AD_ReportView rv ON (p.AD_ReportView_ID=rv.AD_ReportView_ID)"
                + " INNER JOIN AD_Table t ON (rv.AD_Table_ID=t.AD_Table_ID)"
                + " LEFT OUTER JOIN AD_PrintFormat pf ON (p.AD_ReportView_ID=pf.AD_ReportView_ID AND pf.AD_Client_ID IN (0,'" + AD_Client_ID + "')) "
                + "WHERE pi.AD_PInstance_ID='" + pi.GetAD_PInstance_ID() + "' "		//	#2
                + "ORDER BY pf.AD_Client_ID DESC, pf.IsDefault DESC";	//	own first
            IDataReader dr = null;
            try
            {
                dr = DB.ExecuteReader(sql);
                //	Just get first 
                if (dr.Read())
                {
                    AD_ReportView_ID = Util.GetValueOfInt(dr[0].ToString());		//	required
                    whereClause = dr[1].ToString();
                    orderbyClause = dr["OrderByClause"].ToString();
                    if (string.IsNullOrEmpty(whereClause))
                        whereClause = "";
                    //
                    AD_Table_ID = Util.GetValueOfInt(dr[2].ToString());
                    TableName = dr[3].ToString();			//	required for query
                    AD_PrintFormat_ID = Util.GetValueOfInt(dr[4].ToString());		//	required
                    IsForm = "Y".Equals(dr[5].ToString());	//	required
                    Client_ID = Util.GetValueOfInt(dr[6].ToString());
                }
                dr.Close();
            }
            catch (Exception e1)
            {
                if (dr != null)
                {
                    dr.Close();
                }
                log.Log(Level.SEVERE, "(1) - " + sql, e1);
            }
            //	Nothing found
            if (AD_ReportView_ID == 0)
            {
                //	Check Print format in Report Directly
                sql = "SELECT t.AD_Table_ID,t.TableName, pf.AD_PrintFormat_ID, pf.IsForm "
                    + "FROM AD_PInstance pi"
                    + " INNER JOIN AD_Process p ON (pi.AD_Process_ID=p.AD_Process_ID)"
                    + " INNER JOIN AD_PrintFormat pf ON (p.AD_PrintFormat_ID=pf.AD_PrintFormat_ID)"
                    + " INNER JOIN AD_Table t ON (pf.AD_Table_ID=t.AD_Table_ID) "
                    + "WHERE pi.AD_PInstance_ID='" + pi.GetAD_PInstance_ID() + "'";
                IDataReader idr = null;
                try
                {
                    idr = DB.ExecuteReader(sql);
                    while (idr.Read())
                    {
                        whereClause = "";
                        AD_Table_ID = Util.GetValueOfInt(idr[0].ToString());
                        TableName = idr[1].ToString();			//	required for query
                        AD_PrintFormat_ID = Util.GetValueOfInt(idr[2].ToString());		//	required
                        IsForm = "Y".Equals(idr[3].ToString());	//	required
                        Client_ID = AD_Client_ID;
                    }
                    idr.Close();
                }
                catch (Exception e)
                {
                    if (idr != null)
                    {
                        idr.Close();
                    }
                    log.Severe(e.ToString());
                }
                if (AD_PrintFormat_ID == 0)
                {
                    return null;
                }
            }

            //  Create Query from Parameters
            Query query = null;
            if (IsForm && pi.GetRecord_ID() != 0)	//	Form = one record
                query = Query.GetEqualQuery(TableName + "_ID", pi.GetRecord_ID());
            else
                query = Query.Get(ctx, pi.GetAD_PInstance_ID(), TableName);

            //  Add to static where clause from ReportView
            if (whereClause.Length != 0)
                query.AddRestriction(whereClause);

            //Added by Jagmohan Bhatt on 3-Feb-2010 for order by 
            //if (orderbyClause.Length != 0)
            //    query.AddRestriction(" Order By " + orderbyClause);


            //	Get Print Format
            MPrintFormat format = null;
            //Object so = pi.getSerializableObject();
            //if (so instanceof MPrintFormat)
            //	format = (MPrintFormat)so;
            if (format == null && AD_PrintFormat_ID != 0)
            {
                //	We have a PrintFormat with the correct Client
                if (Client_ID == AD_Client_ID)
                    format = MPrintFormat.Get(ctx, AD_PrintFormat_ID, false);
                else
                    format = MPrintFormat.CopyToClient(ctx, AD_PrintFormat_ID, AD_Client_ID);
            }
            if (format != null && format.GetItemCount() == 0)
            {

                format.Delete(true);
                format = null;
            }
            //	Create Format
            if (format == null && AD_ReportView_ID != 0)
                format = MPrintFormat.CreateFromReportView(ctx, AD_ReportView_ID, pi.GetTitle());
            if (format == null)
                return null;
            //
            PrintInfo info = new PrintInfo(pi);
            info.SetAD_Table_ID(AD_Table_ID);

            return new ReportEngine(ctx, format, query, info);
        }

        /// <summary>
        /// Gets the document according to order id
        /// </summary>
        /// <param name="C_Order_ID">order id</param>
        /// <returns>array of int</returns>
        private static int[] GetDocumentWhat(int C_Order_ID)
        {
            int[] what = new int[2];
            what[0] = ORDER;
            what[1] = C_Order_ID;
            //
            String sql = "SELECT dt.DocSubTypeSO "
                + "FROM C_DocType dt, C_Order o "
                + "WHERE o.C_DocType_ID=dt.C_DocType_ID"
                + " AND o.C_Order_ID='" + C_Order_ID + "'";
            String DocSubTypeSO = null;
            IDataReader dr = null;
            try
            {
                dr = DB.ExecuteReader(sql);
                while (dr.Read())
                {
                    DocSubTypeSO = dr[0].ToString();
                }
                dr.Close();
            }
            catch (Exception e)
            {
                if (dr != null)
                {
                    dr.Close();
                }
                log.Severe(e.ToString());
                return null;		//	error
            }

            if (DocSubTypeSO == null)
                DocSubTypeSO = "";
            //	WalkIn Receipt, WalkIn Invoice,
            if (DocSubTypeSO.Equals("WR") || DocSubTypeSO.Equals("WI"))
                what[0] = INVOICE;
            //	WalkIn Pickup,
            else if (DocSubTypeSO.Equals("WP"))
                what[0] = SHIPMENT;
            //	Offer Binding, Offer Nonbinding, Standard Order
            else
                return what;

            //	Get Record_ID of Invoice/Receipt
            if (what[0] == INVOICE)
                sql = "SELECT C_Invoice_ID REC FROM C_Invoice WHERE C_Order_ID='" + C_Order_ID + "'"	//	1
                    + " ORDER BY C_Invoice_ID DESC";
            else
                sql = "SELECT M_InOut_ID REC FROM M_InOut WHERE C_Order_ID='" + C_Order_ID + "'" 	//	1
                    + " ORDER BY M_InOut_ID DESC";
            IDataReader idr = null;
            try
            {

                idr = DB.ExecuteReader(sql);
                bool bl = false;
                if (idr.Read())
                {
                    bl = true;
                    //	if (i == 1 && ADialog.ask(0, null, what[0] == INVOICE ? "PrintOnlyRecentInvoice?" : "PrintOnlyRecentShipment?")) break;
                    what[1] = Util.GetValueOfInt(idr[0].ToString());
                }
                else
                {
                    //if (bl == true)//	No Document Found
                    what[0] = ORDER;
                }

                idr.Close();

            }
            catch (Exception e)
            {
                if (idr != null)
                {
                    idr.Close();
                }
                log.Severe(e.ToString());
                return null;
            }
            return what;
        }

        public void SetQuery(Query query)
        {
            m_query = query;
            if (query == null)
                return;
            //
            SetPrintData();
            if (m_layout != null)
                m_layout.SetPrintData(m_printData, m_query, true);
        }	//	setQuery


        private void SetPrintData()
        {
            if (m_query == null)
                return;
            DataEngine de = new DataEngine(m_printFormat.GetLanguage());
            SetPrintData(de.GetPrintData(m_ctx, m_printFormat, m_query));
            //	m_printData.dump();
        }	//	setPrintData


        public void SetPrintData(PrintData printData)
        {
            if (printData == null)
                return;
            m_printData = printData;
        }	//	setPrintData

        private void SetPrintData(Query query)
        {
            if (query == null)
                return;
            DataEngine de = new DataEngine(m_printFormat.GetLanguage());
            SetPrintData(de.GetPrintData(m_ctx, m_printFormat, query));
            //	m_printData.dump();
        }	//	setPrintData

        /**	Static Logger	*/
        private static VLogger log = VLogger.GetVLogger(typeof(ReportEngine).FullName);

        /**	Context					*/
        private Ctx m_ctx;

        /**	Print Format			*/
        private MPrintFormat m_printFormat;
        /** Print Info				*/
        private PrintInfo m_info;
        /**	Query					*/
        private Query m_query;
        /**	Query Data				*/
        private PrintData m_printData;
        /** Layout					*/
        private LayoutEngine m_layout = null;
        /**	Printer					*/
        private String m_printerName = null;

        static PdfPage _page = null;


        /** Order = 0				*/
        public static int ORDER = 0;
        /** Shipment = 1				*/
        public static int SHIPMENT = 1;
        /** Invoice = 2				*/
        public static int INVOICE = 2;
        /** Project = 3				*/
        public static int PROJECT = 3;
        /** RfQ = 4					*/
        public static int RFQ = 4;
        /** Remittance = 5			*/
        public static int REMITTANCE = 5;
        /** Check = 6				*/
        public static int CHECK = 6;
        /** Dunning = 7				*/
        public static int DUNNING = 7;
        /** Movement = 8            */
        public static int MOVEMENT = 8;
        /** Inventory = 9            */
        public static int INVENTORY = 9;


        private static String[] DOC_TABLES = new String[] {
		"C_Order_Header_v", "M_InOut_Header_v", "C_Invoice_Header_v", "C_Project_Header_v",
		"C_RfQResponse_v",
		"C_PaySelection_Check_v", "C_PaySelection_Check_v",  
		"C_DunningRunEntry_v", "M_Movement", "M_Inventory" };
        private static String[] DOC_BASETABLES = new String[] {
		"C_Order", "M_InOut", "C_Invoice", "C_Project",
		"C_RfQResponse",
		"C_PaySelectionCheck", "C_PaySelectionCheck", 
		"C_DunningRunEntry", "M_Movement", "M_Inventory" };
        private static String[] DOC_IDS = new String[] {
		"C_Order_ID", "M_InOut_ID", "C_Invoice_ID", "C_Project_ID",
		"C_RfQResponse_ID",
		"C_PaySelectionCheck_ID", "C_PaySelectionCheck_ID", 
		"C_DunningRunEntry_ID", "M_Movement_ID",  "M_Inventory_ID" };
        private static int[] DOC_TABLE_ID = new int[] {
		X_C_Order.Table_ID, X_M_InOut.Table_ID, X_C_Invoice.Table_ID, X_C_Project.Table_ID,
		X_C_RfQResponse.Table_ID,
		X_C_PaySelectionCheck.Table_ID, X_C_PaySelectionCheck.Table_ID, 
		X_C_DunningRunEntry.Table_ID, X_M_Movement.Table_ID, X_M_Inventory.Table_ID };
        private static void SetPdfPage(PdfPage page)
        {
            _page = page;
        }

        public static PdfPage GetPdfPage()
        {
            return _page;
        }

        public PdfDocument CreatePDF(string fileName)
        {
            bool done = false;
            Layout();
            PdfDocument document = new PdfDocument();
            System.Windows.Deployment.Current.Dispatcher.BeginInvoke(delegate
            {
                try
                {
                    
                    PdfSharp.Drawing.XGraphics xg = null;

                    for (int page = 0; page < m_layout.GetPages().Count; page++)
                    {
                        XRect pageRectangle = GetRectangleOfPage(page + 1);
                        PdfSharp.Pdf.PdfPage pdfpage = document.AddPage();
                        pdfpage.Height = pageRectangle.Height;
                        pdfpage.Width = pageRectangle.Width;
                        SetPdfPage(pdfpage);
                        xg = PdfSharp.Drawing.XGraphics.FromPdfPage(pdfpage);
                        Page p = (Page)m_layout.GetPages()[page];
                        p.PaintPdf(xg, pageRectangle, true, false);		//	sets context
                        m_layout.GetHeaderFooter().PaintPdf(xg, pageRectangle, true);
                    }

                    done = true;
                }
                catch(Exception ex)
                {
                    ShowMessage.Error(ex.Message, false);
                }
            });

            while (!done)
                Thread.Sleep(10);

            done = false;
            return document;
        }

        private void Layout()
        {
            if (m_printFormat == null)
                throw new Exception("No print format");
            if (m_printData == null)
                throw new Exception("No print data (Delete Print Format and restart)");

            //actaull calling for the reports happens here
            m_layout = new LayoutEngine(m_printFormat, m_printData, m_query);
            //	Printer
            String printerName = m_printFormat.GetPrinterName();
            if (printerName == null && m_info != null)
                printerName = m_info.GetPrinterName();
            //setPrinterName(printerName);
        }	//	layout


        public XRect GetRectangleOfPage(int pageNo)
        {
            int y = MARGIN + ((pageNo - 1) * (GetPaperHeight() + MARGIN));
            return new XRect(MARGIN, 5, GetPaperWidth(), GetPaperHeight());
        }

        /**	Margin around paper				*/
        public static int MARGIN = 5;

        public int GetPaperHeight()
        {
            //return 0;
            return (int)m_layout.GetPaper().GetHeight(true);
        }	//	getPaperHeight

        public int GetPaperWidth()
        {
            //return 0;
            return (int)m_layout.GetPaper().GetWidth(true);
        }	//	getPaperHeight

        public MPrintFormat GetPrintFormat()
        {
            return m_printFormat;
        }	//	getPrintForma

        public void GetLayout()
        {
            ThreadPool.QueueUserWorkItem(delegate
            {
                Layout();
            });
        }

        public View GetView()
        {
            if (m_layout == null)
                Layout();
            if (m_view == null)
            {
                bool pass = false;
                System.Windows.Deployment.Current.Dispatcher.BeginInvoke(delegate
                {
                    m_view = new View(m_layout);
                    pass = true;
                });

                while (!pass)
                    Thread.Sleep(1);

                pass = true;
            }
            return m_view;
        }	//	getView

        public static void PrintConfirm(int type, int Record_ID)
        {
            StringBuilder sql = new StringBuilder();
            if (type == ORDER || type == SHIPMENT || type == INVOICE)
                sql.Append("UPDATE ").Append(DOC_BASETABLES[type])
                    .Append(" SET DatePrinted=SysDate, IsPrinted='Y' WHERE ")
                    .Append(DOC_IDS[type]).Append("=").Append(Record_ID);
            //
            if (sql.Length > 0)
            {
                int no = DB.ExecuteQuery(sql.ToString(), null, null);
                if (no != 1)
                    log.Log(Level.SEVERE, "Updated records=" + no + " - should be just one");
            }
        }	//	printConfirm

        public Ctx GetCtx()
        {
            return m_layout.GetCtx();
        }	//	getCtx


        public String GetName()
        {
            return m_printFormat.GetName();
        }	//	getName

        Viewer mViewer = null;
        public void SetViewer(Viewer viewer)
        {
            mViewer = viewer;
        }

        public void SetPrintFormat(MPrintFormat pf)
        {
            m_printFormat = pf;
            if (m_layout != null)
            {
                SetPrintData();
                m_layout.SetPrintFormat(pf, false);
                m_layout.SetPrintData(m_printData, m_query, true);	//	format changes data
            }
            if (m_view != null)
                m_view.Paint(mViewer);
        }	//	setPrintFormat

        public int GetColumnCount()
        {
            if (m_layout != null)
                return m_layout.GetColumnCount();
            return 0;
        }	//	getColumnCount

        public int GetRowCount()
        {
            return m_printData.GetRowCount();
        }	//	getRowCount
    }
}
